/*--------------------------------------------------------------------------------------+
|
|     $Source: samples/SampleDgnDbEditor/PlaceShipping%Class%Tool.cpp $
|
|  $Copyright: (c) 2014 Bentley Systems, Incorporated. All rights reserved. $
|
+--------------------------------------------------------------------------------------*/
#include "PlaceShipping%Class%Tool.h"

//---------------------------------------------------------------------------------------
// @bsimethod
//---------------------------------------------------------------------------------------
Transform PlaceShipping%Class%Tool::CalculateLocalToWorldTransform()
    {
    DVec3d vec;
    vec.DifferenceOf (m_segment.point[1], m_segment.point[0]);
    return Transform::From (RotMatrix::From1Vector (vec, 0, true), m_segment.point[0]);
    }

//---------------------------------------------------------------------------------------
// @bsimethod
//---------------------------------------------------------------------------------------
double PlaceShipping%Class%Tool::CalculateLength()
    {
    return m_segment.point[0].Distance (m_segment.point[1]);
    }

//---------------------------------------------------------------------------------------
// @bsimethod
//---------------------------------------------------------------------------------------
void PlaceShipping%Class%Tool::_OnDynamicFrame (DgnButtonEventCP ev)
    {
    if (2 != m_numPoints)
        return;

    // set placement and length based on current center-line segment
    Shipping%Class%ItemHandler::Get().SetPlacement (*m_itemPtr, CalculateLocalToWorldTransform());
    m_itemPtr->SetValue (L"Length", ECValue (CalculateLength()));

    // create the graphics that will be shown for this dynamic frame
    PhysicalGraphicsPtr graphicsPtr = DgnGraphicsUtils::GetItemPhysicalGraphics (Shipping%Class%ItemHandler::Get(), m_writeModel, *m_itemPtr);
    if (!graphicsPtr.IsValid())
        return;

    // tell the tool framework to redraw the newly created graphics
    RedrawElems redrawElems;
    redrawElems.SetDrawMode (DgnDrawMode::TempDraw);
    redrawElems.SetDrawPurpose (DrawPurpose::Dynamics);
    redrawElems.SetDynamicsViews (IViewManager::GetActiveViewSet(), ev->GetViewport());
    redrawElems.DoRedraw (graphicsPtr->GetElementHandleR());
    }

//---------------------------------------------------------------------------------------
// @bsimethod
//---------------------------------------------------------------------------------------
bool PlaceShipping%Class%Tool::_OnDataButton (DgnButtonEventCP ev)
    {
    if (0 == m_numPoints)
        {
        _ClearSelection();
        m_segment.point[0] = *ev->GetPoint();
        m_numPoints = 1;
        }
    else
        {
        m_segment.point[1] = *ev->GetPoint();
        m_numPoints = 2;
        }

    return false;
    }

//---------------------------------------------------------------------------------------
// @bsimethod
//---------------------------------------------------------------------------------------
bool PlaceShipping%Class%Tool::_OnDataButtonUp (DgnButtonEventCP ev)
    {
    if (2 != m_numPoints)
        return false;

    // set placement and length based on current center-line segment
    Shipping%Class%ItemHandler::Get().SetPlacement (*m_itemPtr, CalculateLocalToWorldTransform());
    m_itemPtr->SetValue (L"Length", ECValue (CalculateLength()));

    // insert the item's business data
    ECInstanceKey itemKey = Shipping%Class%ItemHandler::Get().InsertItemInstance (m_writeModel.GetDgnProject(), *m_itemPtr);
    if (!itemKey.IsValid())
        {
        _OnRestartTool();
        return false;
        }

    // insert the item's graphical representation
    ElementId elementId;
    if (BSISUCCESS != DgnGraphicsUtils::InsertItemPhysicalGraphics (&elementId, Shipping%Class%ItemHandler::Get(), m_writeModel, itemKey))
        {
        _OnRestartTool();
        return false;
        }

    // commit the transaction
    _CloseCurrentTxn();

    // put the newly created element into the selection set
    SelectionSetManager::GetManager().ReplaceWithElement (m_writeModel.FindElementById (elementId), true);

    _OnRestartTool();
    return false;
    }

//---------------------------------------------------------------------------------------
// @bsimethod
//---------------------------------------------------------------------------------------
bool PlaceShipping%Class%Tool::_OnModelStartDrag (DgnButtonEventCP ev)
    {
    _BeginDynamics();
    return false;
    }

//---------------------------------------------------------------------------------------
// @bsimethod
//---------------------------------------------------------------------------------------
bool PlaceShipping%Class%Tool::_OnModelEndDrag (DgnButtonEventCP ev)
    {
    m_segment.point[1] = *ev->GetPoint();
    m_numPoints = 2;
    return _OnDataButtonUp (ev);
    }

//---------------------------------------------------------------------------------------
// @bsimethod
//---------------------------------------------------------------------------------------
bool PlaceShipping%Class%Tool::_OnModelMotion (DgnButtonEventCP ev)
    {
    if (m_numPoints > 0)
        {
        if (!GetDynamicsStarted())
            _BeginDynamics();

        m_segment.point[1] = *ev->GetPoint();
        m_numPoints = 2;
        }

    return false;
    }

//---------------------------------------------------------------------------------------
// @bsimethod
//---------------------------------------------------------------------------------------
bool PlaceShipping%Class%Tool::_OnResetButton (DgnButtonEventCP ev)
    {
    _OnRestartTool();
    return false;
    }

//---------------------------------------------------------------------------------------
// @bsimethod
//---------------------------------------------------------------------------------------
void PlaceShipping%Class%Tool::_OnRestartTool() 
    {
    if (GetDynamicsStarted())
        _EndDynamics();

    if (_CheckSingleShot())
        return;

    PlaceShipping%Class%Tool* newTool = new PlaceShipping%Class%Tool (m_writeModel);
    newTool->InstallTool();
    }

//---------------------------------------------------------------------------------------
// @bsimethod
//---------------------------------------------------------------------------------------
void PlaceShipping%Class%Tool::_OnPostInstall()
    {
    T_Super::_OnPostInstall();

    AccuDraw::GetInstance().Deactivate();
    AccuSnap::GetInstance().EnableLocate (false);
    AccuSnap::GetInstance().EnableSnap (true);
    }

//---------------------------------------------------------------------------------------
// @bsimethod
//---------------------------------------------------------------------------------------
PlaceShipping%Class%Tool::PlaceShipping%Class%Tool (DgnModelR writeModel) 
    : DgnPrimitiveTool (0), m_writeModel (writeModel), m_numPoints (0)
    {
    m_itemPtr = Shipping%Class%ItemHandler::Get().CreateItemInstance (m_writeModel.GetDgnProject(), "SampleDgnDbEditor", "Shipping%Class%");

    // WIP: should get from the GUI or a template
    m_itemPtr->SetValue (L"Diameter", ECValue (1.0));
    m_itemPtr->SetValue (L"%Class%MaterialType", ECValue ("Cardboard"));
    m_itemPtr->SetValue (L"CapMaterialType", ECValue ("Plastic"));
    }
